package com.qf.framwork.utils;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

/**
 * description: 数据库的连接工具类
 * author: Ken
 * 公众号：Java架构栈
 */
public class ConnectionUtils {

    /**
     * Druid连接池对象
     */
    private static DruidDataSource druidDataSource;

//    private static String url = PropertiesUtils.getProperties("jdbc.url");
//    private static String username = PropertiesUtils.getProperties("jdbc.username");
//    private static String password = PropertiesUtils.getProperties("jdbc.password");

    //用于存放当前线程的数据库连接的ThreadLocal
    private static ThreadLocal<Connection> connThreadLocal = new ThreadLocal<>();
    private static ThreadLocal<Integer> countThreadLocal = new ThreadLocal<>();

    /**
     * 全局加载数据库驱动
     */
    static {
        //加载数据库驱动 - 交给连接池来做
//        try {
//            Class.forName(PropertiesUtils.getProperties("jdbc.driver"));
//        } catch (ClassNotFoundException e) {
//            e.printStackTrace();
//        }

        //初始化Druid连接池
        try {
            druidDataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(PropertiesUtils.getPropertiesObj());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 开启事务
     */
    public static void begin() throws SQLException {
        //从ThreadLocal中获取连接
        Connection connection = connThreadLocal.get();
        if (connection == null) {
            //说明没有往ThreadLocal中放入过连接，我们就创建一个新的连接
            connection = getConnection();
            //对该连接开启事务
            connection.setAutoCommit(false);
            //并且将该连接放入ThreadLocal中
            connThreadLocal.set(connection);
            countThreadLocal.set(1);//标记开启事务的次数
            System.out.println("---->开启事务！" + connection);
        } else {
            System.out.println("---->发现已经开启了事务，则直接沿用当前事务，并且计数器累加");
            Integer count = countThreadLocal.get();
            countThreadLocal.set(++count);
        }
    }


    /**
     * 获取连接
     * @return
     */
    public static Connection getConnection(){
        Connection connection = connThreadLocal.get();
        //直接从ThreadLocal中获取连接
        if (connection != null) {
            return connection;
        }

//        //如果ThreadLocal中没有连接，再返回一个新的连接
//        try {
//            return DriverManager.getConnection(url, username, password);
//        } catch (SQLException e) {
//            e.printStackTrace();
//        }

        //获取连接需要从Druid连接池中获取
        try {
            return druidDataSource.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 提交事务
     */
    public static void commit(){
        Connection connection = connThreadLocal.get();
        if (connection != null) {
            //获得当前的累加器
            Integer count = countThreadLocal.get();
            if (count == 1) {
                try {
                    System.out.println("---->提交事务！" + connection);
                    connection.commit();
                    //提交后再关闭连接
                    connection.close();
                    //清空ThreadLocal
                    connThreadLocal.remove();
                    countThreadLocal.remove();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            } else {
                System.out.println("---->该事务轮不到我提交，累加器--");
                countThreadLocal.set(--count);
            }
        }
    }

    /**
     * 回滚事务
     */
    public static void rollback(){
        Connection connection = connThreadLocal.get();
        if (connection != null) {
            //获得当前的累加器
            Integer count = countThreadLocal.get();
            if (count == 1) {
                try {
                    System.out.println("---->回滚事务！" + connection);
                    connection.rollback();
                    //回滚后再关闭连接
                    connection.close();
                    //清空ThreadLocal
                    connThreadLocal.remove();
                    countThreadLocal.remove();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            } else {
                System.out.println("---->该事务轮不到我回滚，累加器--");
                countThreadLocal.set(--count);
            }
        }
    }


    /**
     * 关闭连接
     */
    public static void close(Connection connection, Statement statement, ResultSet resultSet){
        if (resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if (statement != null) {
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        //如果connection对象是从连接池中获取的，则连接池其实对这个对象的close方法进行了装饰（装饰者模式），
        // 当开发者调用close方法时，并不是关闭连接 而是归还连接到连接池（集合）
        if (connection != null) {
            try {
                //如果当前连接的自动提交为true，才关闭连接，否则不关闭
                //自动提交为true，说明没有开启事务
                if (connection.getAutoCommit()) {
                    connection.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}
